package com.golang.api.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.MultiValueMap;

import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * 签名助手类
 *
 */
public class SignUtils {

	private static final Logger logger = LoggerFactory.getLogger(SignUtils.class);

	/**
	 * 验证签名是否正确
	 * 
	 * @param params
	 *            params 请求参数集，所有参数必须已转换为字符串类型
	 * @param secret
	 *            secret 签名密钥
	 * @param sign
	 *            签名
	 * @return 是否正确：true-正确；false 不正确
	 */
	public static boolean checkSign(MultiValueMap<String, String> params, String secret, String sign) {
		String signNew = SignUtils.getSign(params, secret);
		boolean result = null != sign && sign.equals(signNew);
    if (logger.isDebugEnabled()) {
      logger.debug("checkSign result={}, sign={}, signNew={}", result, sign, signNew);
    }
		return result;
	}

	/**
	 * 签名生成算法
	 * 
	 * @param params
	 *            请求参数集，所有参数必须已转换为字符串类型
	 * @param secret
	 *            签名密钥
	 * @return 签名
	 */
	public static String getSign(MultiValueMap<String, String> params, String secret) {
        // 1.先将参数以其参数名的字典序升序进行排序
        Set<String> sortedParams = new TreeSet<String>(params.keySet());

        StringBuilder builder = new StringBuilder();
        // 2.拼接secret
        builder.append(secret);

        // 3.遍历排序后的字典，将所有参数按"keyvalue"格式拼接在一起
        for (String param : sortedParams) {
            if (params.get(param).size() == 1) {
                builder.append(param).append(params.get(param).get(0));
            }
            if (params.get(param).size() > 1) {
                for (String value : params.get(param)) {
                    builder.append(param).append(value);
                }
            }
        }

        // 4.拼接secret
        builder.append(secret);

        // 5.md5
        if (logger.isDebugEnabled()) {
            logger.debug("before md5 : " + builder.toString());
        }
        return MD5Util.md5Hex(builder.toString());
    }

    public static String getSign(Map<String, String> params, String secret) {
        // 1.先将参数以其参数名的字典序升序进行排序
        Set<String> sortedParams = new TreeSet<String>(params.keySet());

        StringBuilder builder = new StringBuilder();
        // 2.拼接secret
        builder.append(secret);
        for (String param : sortedParams) {
            builder.append(param).append(params.get(param));
        }
        builder.append(secret);
        return MD5Util.md5Hex(builder.toString());
    }
}
